package com.demo.component.locks;

import java.lang.annotation.*;

/**
 * @Author DongXL
 * @Create 2017-09-19 16:22
 *
 * <b>同步锁：</b><br/>
 * 主要作用是在服务器集群环境下保证方法的synchronize；<br/>
 * 标记在方法上，使该方法的执行具有互斥性，并不保证并发执行方法的先后顺序；<br/>
 * 如果原有“A任务”获取锁后任务执行时间超过最大允许持锁时间，且锁被“B任务”获取到，在“B任务”成功获取锁会并不会终止“A任务”的执行；<br/>
 * <br/>
 * <b>注意：</b><br/>
 * 使用过程中需要注意keepMills、toWait、sleepMills、maxSleepMills等参数的场景使用；<br/>
 * 需要安装redis，并使用spring和spring-data-redis等，借助redis NX等方法实现。
 *
 */

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface DistributedLock {

    /**
     * 锁的key<br/>
     * 本参数是必写选项<br/>
     *
     */
    String key();
    /**
     * 持锁时间，超时时间，持锁超过此时间自动丢弃锁<br/>
     * 单位毫秒,默认20秒<br/>
     * 如果为0表示永远不释放锁<br/>
     * 但是没有比较强的业务要求下，不建议设置为0
     */
    long keepMills() default 20 * 1000;
    /**
     * 当获取锁失败，是继续等待还是放弃<br/>
     * 默认为继续等待
     */
    boolean toWait() default true;
    /**
     * 没有获取到锁的情况下且toWait()为继续等待，睡眠指定毫秒数继续获取锁，也就是轮训获取锁的时间<br/>
     * 默认为10毫秒
     *
     * @return
     */
    long sleepMills() default 10;
    /**
     * 锁获取超时时间：<br/>
     * 没有获取到锁的情况下且toWait()为true继续等待，最大等待时间，如果超时抛出
     * {@link java.util.concurrent.TimeoutException}
     * ，可捕获此异常做相应业务处理；<br/>
     * 单位毫秒,默认一分钟，如果设置为0即为没有超时时间，一直获取下去；
     *
     * @return
     */
    long maxSleepMills() default 60 * 1000;

}
